/*******************************************************************************************
 * Copyright (c) 2006-2009 Alex Robson, Rob Simmons, Craig Israel, and Rachel Twyford
 *
 * Use of this software in any form requires that you have both 
 * read and agreed to the following terms:
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions: 
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the 
 * documentation and/or other materials provided with the distribution.
 * Neither the name of Nvigorate nor the names of its contributors may 
 * be used to endorse or promote products derived from this software without 
 * specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ****************************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Nvigorate.Xml;

namespace Nvigorate.Data.Query
{
    [Serializable]
    public abstract class BaseCriterion : ICriterion
    {
        #region Protected Fields

        protected Conjunctions _conjunction = Conjunctions.None;
        protected IQueryObject _field;

        #endregion

        public IQueryObject Field
        {
            get { return _field; }
            set { _field = value; }
        }

        public Conjunctions Conjunction
        {
            get { return _conjunction; }
            set { _conjunction = value; }
        }

        #region Implementation of IClause

        public IClause And()
        {
            _conjunction = Conjunctions.And;
            return this;
        }

        public IClause Or()
        {
            _conjunction = Conjunctions.Or;
            return this;
        }

        #endregion

        #region Operators

        public static CriteriaClause operator &(BaseCriterion criterionA, ICriterion criterionB)
        {
            CriteriaClause clause = new CriteriaClause(criterionA);
            return clause.And(criterionB);
        }

        public static CriteriaClause operator |(BaseCriterion criterionA, ICriterion criterionB)
        {
            CriteriaClause clause = new CriteriaClause(criterionA);
            return clause.Or(criterionB);
        }

        public static CriteriaClause operator &(CriteriaClause clause, BaseCriterion criterion)
        {
            return clause.And(criterion);
        }

        public static CriteriaClause operator |(CriteriaClause clause, BaseCriterion criterion)
        {
            return clause.Or(criterion);
        }

        #endregion

        /* <criterion comparison="" conjunction="">
         *  <field>
         *      <column table="" field="" />
         *  <field>
         *  <values>
         *      <literal></literal>
         *      <function name="">
         *          <literal>param</literal>
         *          <column table="" field="" />
         *      </function>
         *  </values> 
         */

        #region Implementation of ILinqToXml

        public virtual object ParseXElement(XElement element)
        {
            _field = QueryDeserializer
                .DeserializeAmbiguousChild<IQueryObject>(
                element
                    .Descendants("field")
                    .Descendants()
                    .First()
                );

            _conjunction = (Conjunctions)Enum.Parse(typeof(Conjunctions), element.GetAttributeValue("conjunction") ?? "None");
            return this;
        }

        public virtual XElement GetXElementRepresentation()
        {
            return new XElement("criterion",
                                new XAttribute("conjunction", _conjunction),
                                new XElement("field", _field.GetXElementRepresentation())
                );
        }

        #endregion

        #region Implementation of IDisposable

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            throw new System.NotImplementedException();
        }

        #endregion

        public CriteriaClause ToClause()
        {
            return new CriteriaClause(new List<IClause>() { this });
        }
    }
}